package cn.xinfei.xdecision.engine.runner.executor.strategy.component;

import cn.xinfei.xdecision.common.model.component.ComponentVo;
import cn.xinfei.xdecision.common.model.component.scorecard.ScorecardDetail;
import cn.xinfei.xdecision.common.model.component.scorecard.ScorecardDimension;
import cn.xinfei.xdecision.common.model.component.scorecard.vo.ScorecardVersionVo;
import cn.xinfei.xdecision.common.model.component.strategyout.StrategyOutput;
import cn.xinfei.xdecision.common.model.datax.datamanage.Field;
import cn.xinfei.xdecision.common.service.component.scorecard.ScorecardDetailService;
import cn.xinfei.xdecision.common.service.component.scorecard.ScorecardDimensionService;
import cn.xinfei.xdecision.common.service.component.scorecard.ScorecardVersionService;
import cn.xinfei.xdecision.common.service.component.strategyout.StrategyOutputService;
import cn.xinfei.xdecision.common.service.datax.datamanage.FieldService;
import cn.xinfei.xdecision.common.utils.enums.enginex.ComponentTypeEnum;
import cn.xinfei.xdecision.common.utils.enums.enginex.ConditionValueTypeEnum;
import cn.xinfei.xdecision.common.vo.FieldInfoVo;
import cn.xinfei.xdecision.constant.EngineResultEnum;
import cn.xinfei.xdecision.engine.runner.context.XDecisionContext;
import cn.xinfei.xdecision.engine.runner.executor.ComponentHandler;
import cn.xinfei.xdecision.engine.runner.executor.XRunner;
import cn.xinfei.xdecision.engine.runner.executor.model.StateTransmitModel;
import cn.xinfei.xdecision.engine.runner.executor.strategy.EngineComponentRunner;
import cn.xinfei.xdecision.engine.runner.executor.handler.ScorecardNodeHandler;
import cn.xinfei.xdecision.engine.runner.metadata.MetadataProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@XRunner
@Slf4j
@Service
public class ScoreCardComponent extends EngineComponentRunner {

    @Autowired
    private ScorecardNodeHandler scorecardNodeHandler;

    @Autowired
    private FieldService fieldService;

    @Autowired
    protected MetadataProvider metadataProvider;

    @Autowired
    protected StrategyOutputService strategyOutputService;

    @Autowired
    private ScorecardDimensionService scorecardDimensionService;  // 维度

    @Autowired
    private ScorecardDetailService scorecardDetailService;  // 明细

    @Autowired
    private ScorecardVersionService scorecardVersionService;


    @Override
    public String getServiceName() {
        return EngineComponentRunner.PRE + ComponentTypeEnum.SCORECARD.getType();
    }

    @Override
    public void before(ComponentHandler nodeHandler) {
        String componentCode = nodeHandler.getCode();
        ComponentVo componentVo = nodeHandler.getComponentVo();
        Long versionNo = componentVo.getVersionNo();
        List<ScorecardVersionVo> decisionTreeVo = scorecardVersionService.queryVersionListByScorecardId(componentCode, versionNo);
        if (CollectionUtils.isEmpty(decisionTreeVo)) {
            log.warn("scorecard not found.code={},varsionNo={}",componentVo,versionNo);
            return;
        }
        ScorecardVersionVo scorecardVersionVo = decisionTreeVo.get(0);
        Long versionId = scorecardVersionVo.getId();
        componentVo.setVersionId(versionId);
    }

    @Override
    public Map<String, StrategyOutput> getOutputFieldInfo(ComponentHandler nodeHandler) {
        Map<String, StrategyOutput> strategyOutputMap = super.getOutputFieldInfo(nodeHandler);
        Set<String> fieldCodes = new HashSet<>();
        String componentCode = nodeHandler.getCode();
        try {
            ComponentVo componentVo = nodeHandler.getComponentVo();
            Long versionNo = componentVo.getVersionNo();
            try {
                List<ScorecardVersionVo> decisionTreeVos = scorecardVersionService.queryVersionListByScorecardId(componentCode, versionNo);
                for (ScorecardVersionVo versionVo : decisionTreeVos) {
                    String resultFieldCode = versionVo.getResultFieldCode();
                    fieldCodes.add(resultFieldCode);
                }
            } catch (Exception e) {
                log.error("加评分卡信息异常，error={},componentCode={}", e.getMessage(), componentCode, e);
            }
            List<Field> fields = fieldService.queryByEns(fieldCodes);
            fields.stream()
//                    .filter(f -> f.getIsOutput() == 1 || f.getIsInner() == 1)
                    .forEach(field -> {
                        String fieldCode = field.getFieldCode();
                        StrategyOutput output = new StrategyOutput();
                        output.setFieldCode(fieldCode);
                        output.setFieldValue(fieldCode);
                        output.setVarValueType(field.getValueType());
                        output.setValueType(ConditionValueTypeEnum.VARIABLE.getCode());
                        output.setStage(field.getStage());
                        output.setFixed(true);
                        strategyOutputMap.put(fieldCode, output);
                    });
        } catch (Exception e) {
            log.error("DecisionTablesNode,getNodeField:获取评分卡指标异常,engineNode={},error={}", componentCode, e.getMessage(), e);
        }
        return strategyOutputMap;
    }

    @Override
    public void getNodeFieldValue(Set<String> fieldSet, String nodeCode) throws Exception {

    }

    @Override
    public Map<String, FieldInfoVo> getInputFieldInfo(ComponentHandler nodeHandler) {

        Map<String, FieldInfoVo> fieldVos = new HashMap<>();
        Set<String> fieldCodes = new HashSet<>();
        String componentCode = nodeHandler.getCode();
        try {
            ComponentVo componentVo = nodeHandler.getComponentVo();
            Map<String, FieldInfoVo> fieldInfo = metadataProvider.getFieldInfo();


            Long versionId = componentVo.getVersionId();

            List<ScorecardDimension> scorecardDimensions = scorecardDimensionService.getDimensionListByVersionId(versionId);
            List<Integer> dimensionIds = scorecardDimensions.stream().map(item -> item.getId()).collect(Collectors.toList());
            List<ScorecardDetail> scorecardDetails = scorecardDetailService.getDetailListByDimensionIds(dimensionIds);
            fieldCodes.addAll(scorecardDetails.stream().map(item -> item.getFieldCode()).collect(Collectors.toSet()));

            List<Field> fields = fieldService.queryByEns(fieldCodes);
            fields.forEach(field -> {
                String fieldCode = field.getFieldCode();
                FieldInfoVo value = fieldInfo.get(fieldCode);
                if (value != null) {
                    fieldVos.put(fieldCode, value);
                }
            });
        } catch (Exception e) {
            log.error("DecisionTablesNode,getNodeField:获取决策树指标异常,componentCode={},error={}", componentCode, e.getMessage(), e);
        }
        return fieldVos;
    }

    @Override
    public StateTransmitModel runNode(ComponentHandler nodeHandler) {

        String componentCode = nodeHandler.getComponentCode();
        ComponentVo componentVo = nodeHandler.getComponentVo();
        Long versionId = componentVo.getVersionId();

        ScorecardVersionVo versionVo = scorecardVersionService.queryById(versionId);

        BigDecimal totalScore = scorecardNodeHandler.executeDecisionTree(versionVo);

        String resultFieldEn = versionVo.getResultFieldCode();
        if (null != totalScore) {
            setOutput(nodeHandler, resultFieldEn, totalScore);
        }

        log.info("评分卡执行结果，componentCode={},{}={}", componentCode, resultFieldEn, totalScore);

        return XDecisionContext.getContext().getStateContext().setEngineResultEnum(EngineResultEnum.SUCCESS_END);
    }


}
